<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>9. 什么是闭包？闭包的作用是什么？ | Blog</title>
    <meta name="generator" content="VuePress 1.9.10">
    <link rel="icon" href="/blog/img/logo.png">
    <link rel="manifest" href="/blog/manifest.json">
    <link rel="apple-touch-icon" href="/blog/icons/apple-touch-icon-152x152.png">
    <link rel="mask-icon" href="/blog/icons/safari-pinned-tab.svg" color="#3eaf7c">
    <meta name="description" content="blog | js | node | vue | vuepress | webpack">
    <meta name="theme-color" content="#3eaf7c">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="msapplication-TileImage" content="/icons/msapplication-icon-144x144.png">
    <meta name="msapplication-TileColor" content="#000000">
    
    <link rel="preload" href="/blog/assets/css/0.styles.b6b82f87.css" as="style"><link rel="preload" href="/blog/assets/js/app.43c5da00.js" as="script"><link rel="preload" href="/blog/assets/js/2.d3a12b6d.js" as="script"><link rel="preload" href="/blog/assets/js/1.f8bb34da.js" as="script"><link rel="preload" href="/blog/assets/js/64.9777d386.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.fde088a2.js"><link rel="prefetch" href="/blog/assets/js/11.c62b6b34.js"><link rel="prefetch" href="/blog/assets/js/12.27d4f152.js"><link rel="prefetch" href="/blog/assets/js/13.419d7748.js"><link rel="prefetch" href="/blog/assets/js/14.eb7a3d07.js"><link rel="prefetch" href="/blog/assets/js/15.114dfd5c.js"><link rel="prefetch" href="/blog/assets/js/16.85253907.js"><link rel="prefetch" href="/blog/assets/js/17.c2838453.js"><link rel="prefetch" href="/blog/assets/js/18.3256f17f.js"><link rel="prefetch" href="/blog/assets/js/19.d8afd0ae.js"><link rel="prefetch" href="/blog/assets/js/20.0d880388.js"><link rel="prefetch" href="/blog/assets/js/21.33b300c9.js"><link rel="prefetch" href="/blog/assets/js/22.4137860d.js"><link rel="prefetch" href="/blog/assets/js/23.b74cc977.js"><link rel="prefetch" href="/blog/assets/js/24.d99ad412.js"><link rel="prefetch" href="/blog/assets/js/25.ca9a652b.js"><link rel="prefetch" href="/blog/assets/js/26.66d6bac4.js"><link rel="prefetch" href="/blog/assets/js/27.95990a8e.js"><link rel="prefetch" href="/blog/assets/js/28.761c6ea4.js"><link rel="prefetch" href="/blog/assets/js/29.254ffe48.js"><link rel="prefetch" href="/blog/assets/js/3.af33e5d6.js"><link rel="prefetch" href="/blog/assets/js/30.6e4a155b.js"><link rel="prefetch" href="/blog/assets/js/31.665d02a7.js"><link rel="prefetch" href="/blog/assets/js/32.45b461b5.js"><link rel="prefetch" href="/blog/assets/js/33.17a0771a.js"><link rel="prefetch" href="/blog/assets/js/34.af9f8240.js"><link rel="prefetch" href="/blog/assets/js/35.e9dd53af.js"><link rel="prefetch" href="/blog/assets/js/36.e900b84a.js"><link rel="prefetch" href="/blog/assets/js/37.52783c0e.js"><link rel="prefetch" href="/blog/assets/js/38.5cb7cb7f.js"><link rel="prefetch" href="/blog/assets/js/39.0d72378d.js"><link rel="prefetch" href="/blog/assets/js/4.0a92875f.js"><link rel="prefetch" href="/blog/assets/js/40.dfcfa312.js"><link rel="prefetch" href="/blog/assets/js/41.3ae8c9d7.js"><link rel="prefetch" href="/blog/assets/js/42.bed07f3e.js"><link rel="prefetch" href="/blog/assets/js/43.170da95d.js"><link rel="prefetch" href="/blog/assets/js/44.eec82bc0.js"><link rel="prefetch" href="/blog/assets/js/45.b5a61f3a.js"><link rel="prefetch" href="/blog/assets/js/46.dbdb669f.js"><link rel="prefetch" href="/blog/assets/js/47.f3b25bee.js"><link rel="prefetch" href="/blog/assets/js/48.6c3ba867.js"><link rel="prefetch" href="/blog/assets/js/49.2c3070ea.js"><link rel="prefetch" href="/blog/assets/js/5.3b9be48d.js"><link rel="prefetch" href="/blog/assets/js/50.4a2a7438.js"><link rel="prefetch" href="/blog/assets/js/51.b3b493a3.js"><link rel="prefetch" href="/blog/assets/js/52.a56b61d7.js"><link rel="prefetch" href="/blog/assets/js/53.8f36ae1d.js"><link rel="prefetch" href="/blog/assets/js/54.8ee09618.js"><link rel="prefetch" href="/blog/assets/js/55.527c5d9c.js"><link rel="prefetch" href="/blog/assets/js/56.a09690f4.js"><link rel="prefetch" href="/blog/assets/js/57.cf4bc588.js"><link rel="prefetch" href="/blog/assets/js/58.0c8b9d19.js"><link rel="prefetch" href="/blog/assets/js/59.7d09c3f1.js"><link rel="prefetch" href="/blog/assets/js/6.7b96ebf4.js"><link rel="prefetch" href="/blog/assets/js/60.52e5c6db.js"><link rel="prefetch" href="/blog/assets/js/61.afa66052.js"><link rel="prefetch" href="/blog/assets/js/62.d7a75678.js"><link rel="prefetch" href="/blog/assets/js/63.77765300.js"><link rel="prefetch" href="/blog/assets/js/65.deeca199.js"><link rel="prefetch" href="/blog/assets/js/66.aba723e9.js"><link rel="prefetch" href="/blog/assets/js/67.47b5088b.js"><link rel="prefetch" href="/blog/assets/js/68.3178dffd.js"><link rel="prefetch" href="/blog/assets/js/69.a0f4810a.js"><link rel="prefetch" href="/blog/assets/js/7.7e58b9c4.js"><link rel="prefetch" href="/blog/assets/js/70.5b120c62.js"><link rel="prefetch" href="/blog/assets/js/71.2335838f.js"><link rel="prefetch" href="/blog/assets/js/vendors~docsearch.2493936b.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.b6b82f87.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><!----> <span class="site-name">Blog</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blog/" class="nav-link">
  home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="long-ui" class="dropdown-title"><span class="title">long-ui</span> <span class="arrow down"></span></button> <button type="button" aria-label="long-ui" class="mobile-dropdown-title"><span class="title">long-ui</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/ui/" class="nav-link">
  UI简介
</a></li><li class="dropdown-item"><!----> <a href="https://weberlong.github.io/long-ui/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  预览
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/WeberLong/long-ui" target="_blank" rel="noopener noreferrer" class="nav-link external">
  源码
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="/blog/archives/" class="nav-link">
  archives
</a></div><div class="nav-item"><a href="/blog/interview/" class="nav-link router-link-active">
  interview
</a></div> <a href="https://github.com/WeberLong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/blog/" class="nav-link">
  home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="long-ui" class="dropdown-title"><span class="title">long-ui</span> <span class="arrow down"></span></button> <button type="button" aria-label="long-ui" class="mobile-dropdown-title"><span class="title">long-ui</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/ui/" class="nav-link">
  UI简介
</a></li><li class="dropdown-item"><!----> <a href="https://weberlong.github.io/long-ui/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  预览
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/WeberLong/long-ui" target="_blank" rel="noopener noreferrer" class="nav-link external">
  源码
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="/blog/archives/" class="nav-link">
  archives
</a></div><div class="nav-item"><a href="/blog/interview/" class="nav-link router-link-active">
  interview
</a></div> <a href="https://github.com/WeberLong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><a href="/blog/interview/" aria-current="page" class="sidebar-link">面试题</a></li><li><section class="sidebar-group depth-0"><a href="/blog/interview/css/1/" class="sidebar-heading clickable"><span>css</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/interview/css/1.html" class="sidebar-link">1. 如何垂直居中一个元素？</a></li><li><a href="/blog/interview/css/2.html" class="sidebar-link">2. BFC</a></li><li><a href="/blog/interview/css/3.html" class="sidebar-link">3. 移动端1px问题的解决办法</a></li><li><a href="/blog/interview/css/4.html" class="sidebar-link">4. CSS清除浮动的几种方法</a></li><li><a href="/blog/interview/css/5.html" class="sidebar-link">5. opacity:0、visibility:hidden 和 display:none 三者区别？</a></li><li><a href="/blog/interview/css/6.html" class="sidebar-link">6. css绘制三角形五种方法？</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/blog/interview/js/1/" class="sidebar-heading clickable open"><span>js</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/interview/js/1.html" class="sidebar-link">1. 谈谈对this的理解</a></li><li><a href="/blog/interview/js/2.html" class="sidebar-link">2. new操作符具体干了什么呢？如何实现？</a></li><li><a href="/blog/interview/js/3.html" class="sidebar-link">3. 什么是原型链？</a></li><li><a href="/blog/interview/js/4.html" class="sidebar-link">4. 事件委托是什么？</a></li><li><a href="/blog/interview/js/5.html" class="sidebar-link">5. 重排与重绘的区别，什么情况下会触发？</a></li><li><a href="/blog/interview/js/6.html" class="sidebar-link">6. 去除数组重复成员的方法</a></li><li><a href="/blog/interview/js/7.html" class="sidebar-link">7. 深拷贝和浅拷贝的区别是什么？实现一个深拷贝</a></li><li><a href="/blog/interview/js/8.html" class="sidebar-link">8. 柯里化函数实现</a></li><li><a href="/blog/interview/js/9.html" aria-current="page" class="active sidebar-link">9. 什么是闭包？闭包的作用是什么？</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/interview/js/9.html#闭包的定义" class="sidebar-link">闭包的定义</a></li><li class="sidebar-sub-header"><a href="/blog/interview/js/9.html#闭包特性" class="sidebar-link">闭包特性</a></li><li class="sidebar-sub-header"><a href="/blog/interview/js/9.html#闭包的作用" class="sidebar-link">闭包的作用</a></li></ul></li><li><a href="/blog/interview/js/10.html" class="sidebar-link">10. Promise的 all/any/race/allSettled 方法的区别</a></li><li><a href="/blog/interview/js/11.html" class="sidebar-link">11. jsonp的原理是什么？</a></li><li><a href="/blog/interview/js/12.html" class="sidebar-link">12. 介绍一下js的节流与防抖?</a></li><li><a href="/blog/interview/js/13.html" class="sidebar-link">13. js的事件循环是什么？</a></li><li><a href="/blog/interview/js/14.html" class="sidebar-link">14. 手写call、apply及bind函数</a></li><li><a href="/blog/interview/js/15.html" class="sidebar-link">15. ['1', '2', '3'].map(parseInt)执行结果，what &amp; why ?</a></li><li><a href="/blog/interview/js/16.html" class="sidebar-link">16. 手写一个Promise</a></li><li><a href="/blog/interview/js/17.html" class="sidebar-link">17. js数组扁平化的六种方式</a></li><li><a href="/blog/interview/js/18.html" class="sidebar-link">18. webpack相关问题</a></li><li><a href="/blog/interview/js/19.html" class="sidebar-link">19. http和https的区别</a></li><li><a href="/blog/interview/js/20.html" class="sidebar-link">20. 实现 instanceOf</a></li><li><a href="/blog/interview/js/21.html" class="sidebar-link">21. 打印出1-10000之间的所有对称数</a></li><li><a href="/blog/interview/js/22.html" class="sidebar-link">22. for of, for in和forEach, map的区别？</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/blog/interview/frame/1/" class="sidebar-heading clickable"><span>框架</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/interview/frame/1.html" class="sidebar-link">1. Vue基础</a></li><li><a href="/blog/interview/frame/2.html" class="sidebar-link">2. 30道vue面试题</a></li></ul></section></li><li><section class="sidebar-group depth-0"><a href="/blog/interview/leetcode/1/" class="sidebar-heading clickable"><span>算法</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/interview/leetcode/1.html" class="sidebar-link">1. JS面试中常见的算法题</a></li><li><a href="/blog/interview/leetcode/2.html" class="sidebar-link">2. 说说你对二分查找的理解？如何实现？</a></li><li><a href="/blog/interview/leetcode/3.html" class="sidebar-link">3. 介绍下深度优先遍历和广度优先遍历，如何实现？</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="_9-什么是闭包-闭包的作用是什么"><a href="#_9-什么是闭包-闭包的作用是什么" class="header-anchor">#</a> 9. 什么是闭包？闭包的作用是什么？</h1> <h2 id="闭包的定义"><a href="#闭包的定义" class="header-anchor">#</a> 闭包的定义</h2> <p>《JavaScript高级程序设计》:</p> <blockquote><p>闭包是指有权访问另一个函数作用域中的变量的函数</p></blockquote> <p>《JavaScript权威指南》：</p> <blockquote><p>从技术的角度讲，所有的JavaScript函数都是闭包：它们都是对象，它们都关联到作用域链。</p></blockquote> <p>《你不知道的JavaScript》</p> <blockquote><p>当函数可以记住并访问所在的词法作用域时，就产生了闭包，即使函数是在当前词法作用域之外执行。</p></blockquote> <h2 id="闭包特性"><a href="#闭包特性" class="header-anchor">#</a> 闭包特性</h2> <ul><li>(1)函数内再嵌套函数</li> <li>(2)内部函数可以引用外层的参数和变量</li> <li>(3)参数和变量不会被垃圾回收机制回收</li></ul> <p>创建一个闭包</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> func <span class="token operator">=</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//输出2</span>
</code></pre></div><p>闭包使得函数可以继续访问定义时的词法作用域。拜 fn 所赐，在 foo() 执行后，foo 内部作用域不会被销毁。</p> <h2 id="闭包的作用"><a href="#闭包的作用" class="header-anchor">#</a> 闭包的作用</h2> <ol><li><p>能够访问函数定义时所在的词法作用域(阻止其被回收)。</p></li> <li><p>私有化变量</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">base</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span> <span class="token comment">//私有变量</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token function-variable function">getX</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> x<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token function">base</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj<span class="token punctuation">.</span><span class="token function">getX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//10</span>
</code></pre></div><ol start="3"><li>模拟块级作用域</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    a<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">j</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
a<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 6</span>
</code></pre></div><ol start="4"><li>创建模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">coolModule</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> name <span class="token operator">=</span> <span class="token string">'Yvette'</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> age <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">sayName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">function</span> <span class="token function">sayAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
        sayName<span class="token punctuation">,</span>
        sayAge
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> info <span class="token operator">=</span> <span class="token function">coolModule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
info<span class="token punctuation">.</span><span class="token function">sayName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//'Yvette'</span>
</code></pre></div><p>模块模式具有两个必备的条件(来自《你不知道的JavaScript》)</p> <ul><li>必须有外部的封闭函数，该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)</li> <li>封闭函数必须返回至少一个内部函数，这样内部函数才能在私有作用域中形成闭包，并且可以访问或者修改私有的状态。</li></ul> <hr> <p><strong>鄙视题：</strong></p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token parameter">n<span class="token punctuation">,</span>o</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token function-variable function">fun</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">m</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token function">fun</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> a<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> a<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> a<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//undefined,?,?,?</span>
<span class="token keyword">var</span> b <span class="token operator">=</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//undefined,?,?,?</span>
<span class="token keyword">var</span> c <span class="token operator">=</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> c<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> c<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//undefined,?,?,?</span>
<span class="token comment">// 问: 三行a,b,c的输出分别是什么？ </span>
</code></pre></div><p><strong>解答</strong></p> <ul><li>1、第一行a</li></ul> <p>var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);
可以得知，第一个fun(0)是在调用第一层fun函数。第二个fun(1)是在调用前一个fun的返回值的fun函数，所以：</p> <p>第后面几个fun(1),fun(2),fun(3),函数都是在调用第二层fun函数。</p> <p>遂：</p> <p>在第一次调用fun(0)时，o为undefined；</p> <p>第二次调用fun(1)时m为1，此时fun闭包了外层函数的n，也就是第一次调用的n=0，即m=1，n=0，并在内部调用第一层fun函数fun(1,0);所以o为0；</p> <p>第三次调用fun(2)时m为2，但依然是调用a.fun，所以还是闭包了第一次调用时的n，所以内部调用第一层的fun(2,0);所以o为0</p> <p>第四次同理；</p> <p>即：最终答案为undefined,0,0,0</p> <ul><li>2、第二行b</li></ul> <p>var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
先从fun(0)开始看，肯定是调用的第一层fun函数；而他的返回值是一个对象，所以第二个fun(1)调用的是第二层fun函数，后面几个也是调用的第二层fun函数。</p> <p>遂：</p> <p>在第一次调用第一层fun(0)时，o为undefined；</p> <p>第二次调用 .fun(1)时m为1，此时fun闭包了外层函数的n，也就是第一次调用的n=0，即m=1，n=0，并在内部调用第一层fun函数fun(1,0);所以o为0；</p> <p>第三次调用 .fun(2)时m为2，此时当前的fun函数不是第一次执行的返回对象，而是第二次执行的返回对象。而在第二次执行第一层fun函数时时(1,0)所以n=1,o=0,返回时闭包了第二次的n，遂在第三次调用第三层fun函数时m=2,n=1，即调用第一层fun函数fun(2,1)，所以o为1；</p> <p>第四次调用 .fun(3)时m为3，闭包了第三次调用的n，同理，最终调用第一层fun函数为fun(3,2)；所以o为2；</p> <p>即最终答案：undefined,0,1,2</p> <ul><li>3、第三行c</li></ul> <p>var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
根据前面两个例子，可以得知：</p> <p>fun(0)为执行第一层fun函数，.fun(1)执行的是fun(0)返回的第二层fun函数，这里语句结束，遂c存放的是fun(1)的返回值，而不是fun(0)的返回值，所以c中闭包的也是fun(1)第二次执行的n的值。c.fun(2)执行的是fun(1)返回的第二层fun函数，c.fun(3)执行的也是fun(1)返回的第二层fun函数。</p> <p>遂：</p> <p>在第一次调用第一层fun(0)时，o为undefined；</p> <p>第二次调用 .fun(1)时m为1，此时fun闭包了外层函数的n，也就是第一次调用的n=0，即m=1，n=0，并在内部调用第一层fun函数fun(1,0);所以o为0；</p> <p>第三次调用 .fun(2)时m为2，此时fun闭包的是第二次调用的n=1，即m=2，n=1，并在内部调用第一层fun函数fun(2,1);所以o为1；</p> <p>第四次.fun(3)时同理，但依然是调用的第二次的返回值，遂最终调用第一层fun函数fun(3,1)，所以o还为1</p> <p>即最终答案：undefined,0,1,1</p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/blog/interview/js/8.html" class="prev">
        8. 柯里化函数实现
      </a></span> <span class="next"><a href="/blog/interview/js/10.html">
        10. Promise的 all/any/race/allSettled 方法的区别
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/blog/assets/js/app.43c5da00.js" defer></script><script src="/blog/assets/js/2.d3a12b6d.js" defer></script><script src="/blog/assets/js/1.f8bb34da.js" defer></script><script src="/blog/assets/js/64.9777d386.js" defer></script>
  </body>
</html>
